package com.jumi.microservice.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jumi.microservice.common.constant.RequestConstant;
import com.jumi.microservice.common.exception.BusinessException;
import com.jumi.microservice.common.page.TableDataInfo;
import com.jumi.microservice.common.redis.RedisCache;
import com.jumi.microservice.common.utils.ObjectUtils;
import com.jumi.microservice.constant.*;
import com.jumi.microservice.domain.*;
import com.jumi.microservice.domain.GoodsDTO;
import com.jumi.microservice.domain.GoodsShowDTO;
import com.jumi.microservice.domain.GoodsQuery;
import com.jumi.microservice.mapper.BrandMapper;
import com.jumi.microservice.mapper.CategoryMapper;
import com.jumi.microservice.mapper.GoodsMapper;
import com.jumi.microservice.mapper.GoodsSkuMapper;
import com.jumi.microservice.mapper.*;
import com.jumi.microservice.service.GoodsService;
import com.jumi.microservice.state.GoodsStateManager;
import com.jumi.microservice.stock.dto.commodity.CommodityApplyDTO;
import com.jumi.microservice.stock.dto.commodity.CommodityApplyDetailDTO;
import com.jumi.microservice.stock.dto.commodity.CommodityApplyMaterialDTO;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * 商品管理service组件接口
 *
 * @author Administrator
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class GoodsServiceImpl implements GoodsService {

    private static final Logger logger = LoggerFactory.getLogger(GoodsServiceImpl.class);

    /**
     * 商品管理mapper组件
     */
    @Autowired
    private GoodsMapper goodsMapper;

    /**
     * 商品sku管理mapper组件
     */
    @Autowired
    private GoodsSkuMapper goodsSkuMapper;

    /**
     * 商品状态管理器
     */
    @Autowired
    private GoodsStateManager goodsStateManager;

    /**
     * 商品品牌管理mapper组件
     */
    @Autowired
    private BrandMapper brandMapper;

    /**
     * 商品分类管理mapper组件
     */
    @Autowired
    private CategoryMapper categoryMapper;

    /**
     * 商品图片管理mapper组件
     */
    @Autowired
    private GoodsPictureMapper goodsPictureMapper;

    /**
     * 商品供应商管理mapper组件
     */
    @Autowired
    private SupplierMapper supplierMapper;

    /**
     * 商品sku属性值管理mapper组件
     */
    @Autowired
    private GoodsSkuPropertyValueMapper goodsSkuPropertyValueMapper;

    /**
     * 商品spu定时上架调度mapper组件
     */
    @Autowired
    private GoodsScheduleMapper goodsScheduleMapper;

    @Autowired
    private CommodityMaterialSkuRelationshipMapper commoditySupplySkuRelationshipMapper;

    @Autowired
    private CommodityMaterialSpuRelationshipMapper commoditySupplySpuRelationshipMapper;

    @Autowired
    private OrderStockLogMapper orderStockLogMapper;

    @Autowired
    private RedisCache redisCache;

    /**
     * 运费模板管理mapper组件
     */
    @Autowired
    private FreightTemplateMapper freightTemplateMapper;
    /**
     * 商品spu编码前缀
     */
    private static final String SPU_PREFIX = "SPU_";

    /**
     * 商品sku编码前缀
     */
    private static final String SKU_PREFIX = "SKU_";

    /**
     * 时间格式：yyyy-MM-dd HH:mm
     */
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    /**
     * 商品spu和税收对应关系mapper组件
     */
    @Autowired
    private GoodsTaxMapper goodsTaxMapper;


    @Autowired
    private FreightTemplateExtendMapper freightTemplateExtendMapper;

    /**
     * 分页查询标签绑定的商品
     *
     * @param labelId 标签ID
     * @return 商品列表
     */
    @Override
    public List<GoodsDTO> listGoodsByLabelId(Long labelId) {
        LambdaQueryWrapper<GoodsDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        wrapper.like(labelId != null, GoodsDO::getGoodsLabel, String.valueOf(labelId));
        List<GoodsDO> goods = goodsMapper.selectList(wrapper);

        Map<Long, List<GoodsDTO>> labelGoodsMap = new HashMap<>();
        List<GoodsDTO> goodsDtos = convertGoodsDoList2DtoList(goods);
        for (GoodsDTO goodsDTO : goodsDtos) {
            String[] labels = goodsDTO.getGoodsLabel().split(",");

            for (String label : labels) {
                long labelKey = Long.parseLong(label);
                if (labelGoodsMap.containsKey(labelKey)) {
                    labelGoodsMap.get(labelKey).add(goodsDTO);
                } else {
                    List<GoodsDTO> goodsDTOList = new ArrayList<>();
                    goodsDTOList.add(goodsDTO);
                    labelGoodsMap.put(labelKey, goodsDTOList);
                }
            }
        }

        return labelGoodsMap.getOrDefault(labelId, new ArrayList<>());
    }

    /**
     * 商品搜索
     *
     * @param goodsSearchQuery 商品查询条件
     * @return 商品DTO值对象集合
     */
    @Override
    public List<GoodsDTO> searchGoodsByPage(GoodsSearchQuery goodsSearchQuery, boolean isFront) {
        QueryWrapper<GoodsDO> goodsWrapper = new QueryWrapper<>();
        if (isFront) {
            goodsWrapper.eq("is_del", StatusEnum.STATUS_NO.getCode());
            goodsWrapper.eq("goods_state", GoodsStatus.PUTTED_ON_SHELVES.getCode());
        }
        goodsWrapper.like(StringUtils.isNotEmpty(goodsSearchQuery.getKeyWord()), "goods_name", goodsSearchQuery.getKeyWord());
        List<GoodsDO> goodsList = goodsMapper.selectList(goodsWrapper);

        goodsList.forEach(goods -> {
            Object cacheObject = redisCache.getCacheObject(GoodsKeyConstant.POSTAGEGOODS + goods.getId());
            if (!Objects.isNull(cacheObject)) {
                goods.setGoodsPrice(BigDecimal.ZERO);
            }
        });

        if (goodsSearchQuery.getGoodsPriceFrom() != null && goodsSearchQuery.getGoodsPriceTo() == null) {
            goodsList = goodsList.stream()
                    .filter(goodsDO -> goodsDO.getGoodsPrice().compareTo(goodsSearchQuery.getGoodsPriceFrom()) > -1)
                    .collect(Collectors.toList());
        } else if (goodsSearchQuery.getGoodsPriceFrom() == null && goodsSearchQuery.getGoodsPriceTo() != null) {
            goodsList = goodsList.stream()
                    .filter(goodsDO -> goodsDO.getGoodsPrice().compareTo(goodsSearchQuery.getGoodsPriceTo()) < 1)
                    .collect(Collectors.toList());
        } else if (goodsSearchQuery.getGoodsPriceFrom() != null && goodsSearchQuery.getGoodsPriceTo() != null) {
            goodsList = goodsList.stream()
                    .filter(goodsDO -> goodsDO.getGoodsPrice().compareTo(goodsSearchQuery.getGoodsPriceFrom()) > -1)
                    .filter(goodsDO -> goodsDO.getGoodsPrice().compareTo(goodsSearchQuery.getGoodsPriceTo()) < 1)
                    .collect(Collectors.toList());
        }

        return convertGoodsDoList2DtoList(goodsList);
    }

    /**
     * 商品分页查询
     *
     * @param goodsQuery 商品查询条件
     * @return List<GoodsShowDTO> 商品DTO集合
     */
    @Override
    public List<GoodsShowDTO> listGoodsByPage(GoodsQuery goodsQuery) {
        LambdaQueryWrapper<GoodsDO> goodsWrapper = Wrappers.lambdaQuery();
        goodsWrapper.eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        goodsWrapper.eq(goodsQuery.getId() != null, GoodsDO::getId, goodsQuery.getId());
        goodsWrapper.like(StringUtils.isNotEmpty(goodsQuery.getGoodsName()), GoodsDO::getGoodsName, goodsQuery.getGoodsName());
        goodsWrapper.eq(goodsQuery.getGoodsState() != null, GoodsDO::getGoodsState, goodsQuery.getGoodsState());
        goodsWrapper.eq(goodsQuery.getSupplyId() != null, GoodsDO::getSupplyId, goodsQuery.getSupplyId());

        if (goodsQuery.getGoodsType() != null) {
            goodsWrapper.in(GoodsDO::getGoodsType,
                    Arrays.asList(goodsQuery.getGoodsType().split(",")));
        }
        goodsWrapper.ge(StringUtils.isNotEmpty(goodsQuery.getUpdateTimeFrom()), GoodsDO::getUpdateTime, goodsQuery.getUpdateTimeFrom());
        goodsWrapper.le(StringUtils.isNotEmpty(goodsQuery.getUpdateTimeTo()), GoodsDO::getUpdateTime, goodsQuery.getUpdateTimeTo());
        goodsWrapper.eq(goodsQuery.getBrandId() != null, GoodsDO::getBrandId, goodsQuery.getBrandId());
        goodsWrapper.eq(goodsQuery.getCategoryId() != null, GoodsDO::getCreatgroySecond, goodsQuery.getCategoryId());
        goodsWrapper.orderByDesc(GoodsDO::getId);

        List<GoodsDO> goodsList = goodsMapper.selectList(goodsWrapper);
        List<GoodsShowDTO> goodsShows = new ArrayList<>(goodsList.size());

        for (GoodsDO goods : goodsList) {
            GoodsShowDTO goodsShow = new GoodsShowDTO();
            goodsShow.setGoodsId(goods.getId());
            goodsShow.setGoodsImage(goods.getGoodsImage());
            goodsShow.setGoodsName(goods.getGoodsName());
            goodsShow.setBrandName(brandMapper.selectById(goods.getBrandId()).getBrandName());
            String firstCreatgroyName = categoryMapper.selectById(goods.getCreatgroyFirst()).getCategoryName();
            String secondCreatgroyName = categoryMapper.selectById(goods.getCreatgroySecond()).getCategoryName();
            goodsShow.setCategoryName(firstCreatgroyName + ">" + secondCreatgroyName);
            goodsShow.setGoodsMarketprice(goods.getGoodsMarketprice());
            goodsShow.setGoodsPrice(goods.getGoodsPrice());
            goodsShow.setGoodsType(goods.getGoodsType());

            Integer goodsState = goods.getGoodsState();
            if (goodsState.equals(GoodsStatus.PUTTED_ON_SHELVES.getCode())) {
                goodsShow.setGoodsState(GoodsStatus.PUTTED_ON_SHELVES.getDesc());
            } else if (goodsState.equals(GoodsStatus.PULLED_OFF_SHELVES.getCode())) {
                goodsShow.setGoodsState(GoodsStatus.PULLED_OFF_SHELVES.getDesc());
            } else if (goodsState.equals(GoodsStatus.FIX_PUTTED_ON_SHELVES.getCode())) {
                goodsShow.setGoodsState(GoodsStatus.FIX_PUTTED_ON_SHELVES.getDesc());
            } else {
                goodsShow.setGoodsState(GoodsStatus.UNKNOWN.getDesc());
            }
            List<GoodsSkuDO> goodsSkuList = goodsSkuMapper.selectList(Wrappers.<GoodsSkuDO>lambdaQuery()
                    .eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                    .eq(GoodsSkuDO::getGoodsId, goods.getId())
                    .eq(GoodsSkuDO::getGoodsPrice, goods.getGoodsPrice()));

            if (goodsSkuList.size() != 0) {
                GoodsSkuDO goodsSku = goodsSkuList.get(0);
                goodsShow.setPlatinumPrice(goodsSku.getPlatinumPrice());
                goodsShow.setDiamondsPrice(goodsSku.getDiamondsPrice());
                goodsShow.setKingPrice(goodsSku.getKingPrice());
                goodsShow.setGetOrderPrice(goodsSku.getGetOrderPrice());
            }
            goodsShows.add(goodsShow);
        }
        return goodsShows;
    }

    /**
     * 根据id查询商品
     *
     * @param id 商品id
     * @return 商品
     */
    @Override
    public GoodsDTO getGoodsById(Long id) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(id == null);
        GoodsDTO goodsDto = convertGoodsDo2Dto(goodsMapper.selectById(id));

        ExceptionEnum.FAIL_NULL.doThrowIf(goodsDto == null);

        LambdaQueryWrapper<GoodsPictureDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GoodsPictureDO::getGoodsId, id);

        List<GoodsPictureDO> goodsPictures = goodsPictureMapper.selectList(wrapper);
        goodsDto.setGoodsPicture(convertGoodsPictureDoList2DtoList(goodsPictures));

        FreightTemplateDO freightTemplateDO = freightTemplateMapper.selectById(goodsDto.getTransportId());
        goodsDto.setTransportName(freightTemplateDO.getTemplateName());

        LambdaQueryWrapper<GoodsTaxDO> taxWrapper = Wrappers.lambdaQuery();
        taxWrapper.eq(GoodsTaxDO::getSpuId, id);
        GoodsTaxDO goodsTax = goodsTaxMapper.selectOne(taxWrapper);

        if (Objects.nonNull(goodsTax)) {
            GoodsTaxDTO goodsTaxDto = convertGoodsTaxDo2Dto(goodsTax);
            goodsDto.setGoodsTax(goodsTaxDto);
        }

        LambdaQueryWrapper<GoodsSkuDO> goodsSkuWrapper = Wrappers.lambdaQuery();
        goodsSkuWrapper.eq(GoodsSkuDO::getGoodsId, id);
        List<GoodsSkuDO> goodsSkus = goodsSkuMapper.selectList(goodsSkuWrapper);

        List<GoodsSkuDTO> goodsSkuDtos = convertGoodsSkuList2DtoList(goodsSkus);
        for (GoodsSkuDTO goodsSkuDto : goodsSkuDtos) {
            LambdaQueryWrapper<GoodsSkuPropertyValueDO> goodsSkuPropertyValueWrapper = Wrappers.lambdaQuery();
            goodsSkuPropertyValueWrapper.eq(GoodsSkuPropertyValueDO::getGoodsSkuId, goodsSkuDto.getId());

            List<GoodsSkuPropertyValueDO> goodsSkuPropertyValues = goodsSkuPropertyValueMapper.selectList(goodsSkuPropertyValueWrapper);
            List<GoodsSkuPropertyValueDTO> goodsSkuPropertyValueDtos = convertGoodsSkuPropertyValueList2DtoList(goodsSkuPropertyValues);
            goodsSkuDto.setGoodsSkuPropertyValue(goodsSkuPropertyValueDtos);

            //查询物料
            LambdaQueryWrapper<CommodityMaterialSkuRelationshipDO> cmsrQueryWrapper = Wrappers.lambdaQuery();
            cmsrQueryWrapper.eq(CommodityMaterialSkuRelationshipDO::getSkuId, goodsSkuDto.getId());
            List<CommodityMaterialSkuRelationshipDO> commodityMaterialSkuRelationships
                    = commoditySupplySkuRelationshipMapper.selectList(cmsrQueryWrapper);

            List<CommodityMaterialSkuRelationshipDTO> commodityMaterialSkuRelationshipDtos =
                    convertCommodityMaterialSkuRelationshipList2DtoList(commodityMaterialSkuRelationships);
            goodsSkuDto.setCommodityMaterialSkuRelationship(commodityMaterialSkuRelationshipDtos);
        }
        goodsDto.setGoodsSkus(goodsSkuDtos);

        LambdaQueryWrapper<CommodityMaterialSpuRelationshipDO> cmSpuWrapper = Wrappers.lambdaQuery();
        cmSpuWrapper.eq(CommodityMaterialSpuRelationshipDO::getSpuId, id);
        List<CommodityMaterialSpuRelationshipDO> commodityMaterialSpuRelationshipDOS = commoditySupplySpuRelationshipMapper.selectList(cmSpuWrapper);
        List<CommodityMaterialSpuRelationshipDTO> commodityMaterialSpuRelationshipDTOS = convertCommodityMaterialSpuRelationshipDoList2DtoList(commodityMaterialSpuRelationshipDOS);

        for (CommodityMaterialSpuRelationshipDTO commodityMaterialSpuRelationshipDto : commodityMaterialSpuRelationshipDTOS) {
            Long spuId = commodityMaterialSpuRelationshipDto.getSpuId();
            Long materialSpuId = commodityMaterialSpuRelationshipDto.getMaterialSpuId();

            LambdaQueryWrapper<CommodityMaterialSkuRelationshipDO> cmSkuWrapper = Wrappers.lambdaQuery();
            cmSkuWrapper.eq(CommodityMaterialSkuRelationshipDO::getSpuId, spuId);
            cmSkuWrapper.eq(CommodityMaterialSkuRelationshipDO::getMaterialSpuId, materialSpuId);
            List<CommodityMaterialSkuRelationshipDO> commodityMaterialSkuRelationships = commoditySupplySkuRelationshipMapper.selectList(cmSkuWrapper);

            commodityMaterialSpuRelationshipDto.setCommodityMaterialSkuRelationship(convertCommodityMaterialSkuRelationshipList2DtoList(commodityMaterialSkuRelationships));
        }

        goodsDto.setCommodityMaterialSpuRelationship(commodityMaterialSpuRelationshipDTOS);

        if (goodsDto.getGoodsState().equals(GoodsStatus.FIX_PUTTED_ON_SHELVES.getCode())) {
            LambdaQueryWrapper<GoodsScheduleDO> goodsScheduleLambdaQueryWrapper = Wrappers.lambdaQuery();
            goodsScheduleLambdaQueryWrapper.eq(GoodsScheduleDO::getGoodsId, id);
            goodsScheduleLambdaQueryWrapper.eq(GoodsScheduleDO::getIsSuccess, NumberConstant.NUMBER_ZERO);
            GoodsScheduleDO goodsSchedule = goodsScheduleMapper.selectOne(goodsScheduleLambdaQueryWrapper);
            LocalDateTime goodsSelltime = goodsSchedule.getGoodsSelltime();
            DateTimeFormatter df = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
            goodsDto.setGoodsSelltime(df.format(goodsSelltime));
        }
        return goodsDto;
    }


    private List<CommodityMaterialSpuRelationshipDTO> convertCommodityMaterialSpuRelationshipDoList2DtoList(
            List<CommodityMaterialSpuRelationshipDO> commodityMaterialSpuRelationshipDOList) {
        List<CommodityMaterialSpuRelationshipDTO> goodsDtos = null;
        try {
            goodsDtos = ObjectUtils.convertList(commodityMaterialSpuRelationshipDOList, CommodityMaterialSpuRelationshipDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsDtos;
    }

    /**
     * 根据id查询商品
     *
     * @param id 商品id
     * @return 商品
     */
    @Override
    public GoodsDTO getGoodsDetailById(Long id) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(id == null);
        GoodsDTO goodsDto = convertGoodsDo2Dto(goodsMapper.selectById(id));
        ExceptionEnum.FAIL_NULL.doThrowIf(goodsDto == null);
        return goodsDto;
    }

    /**
     * 新增商品
     *
     * @param goodsDto 商品VO
     * @param request  request
     * @return List<GoodsSkuDTO> sku DTO集合
     */
    @Override
    public List<GoodsSkuDTO> addGoods(GoodsDTO goodsDto, HttpServletRequest request) {
        checkGoods(goodsDto);

        GoodsDO goods = convertGoodsDto2Do(goodsDto);
        LocalDateTime localDateTime = LocalDateTime.now();

        //保存商品spu基本信息
        long spuSnowId = IdUtil.getSnowflake(getWorkId(), getDataCenterId()).nextId();
        goods.setSpuCode(SPU_PREFIX + spuSnowId);
        goods.setCreateTime(localDateTime);
        goods.setUpdateTime(localDateTime);
        String userName = request.getHeader(RequestConstant.ADMIN_NAME);
        goods.setCreater(userName);
        goods.setModifier(userName);
        List<GoodsSkuDTO> goodsSkuDtos = goodsDto.getGoodsSkus();
        goodsSkuDtos.sort((x, y) -> Double.compare(x.getGoodsPrice().doubleValue(), y.getGoodsPrice().doubleValue()));
        int numberZero = NumberConstant.NUMBER_ZERO.intValue();
        if (goodsSkuDtos.size() > numberZero) {
            goods.setGoodsPrice(goodsSkuDtos.get(numberZero).getGoodsPrice());
            goods.setGoodsMarketprice(goodsSkuDtos.get(numberZero).getGoodsMarketprice());
        }
        goodsMapper.insert(goods);

        //保存商品spu和物料的对应关系信息
        List<CommodityMaterialSpuRelationshipDTO> commodityMaterialSpuRelationship = goodsDto.getCommodityMaterialSpuRelationship();
        for (CommodityMaterialSpuRelationshipDTO CommodityMaterialSpuRelationshipDto : commodityMaterialSpuRelationship) {
            CommodityMaterialSpuRelationshipDO commodityMaterialSpuRelationshipDO = new CommodityMaterialSpuRelationshipDO();

            commodityMaterialSpuRelationshipDO.setSpuId(goods.getId());
            commodityMaterialSpuRelationshipDO.setMaterialSpuId(CommodityMaterialSpuRelationshipDto.getMaterialSpuId());
            commodityMaterialSpuRelationshipDO.setMaterialSpuCode(CommodityMaterialSpuRelationshipDto.getMaterialSpuCode());
            commodityMaterialSpuRelationshipDO.setMaterialSpuName(CommodityMaterialSpuRelationshipDto.getMaterialSpuName());
            commodityMaterialSpuRelationshipDO.setUnitId(CommodityMaterialSpuRelationshipDto.getUnitId());
            commodityMaterialSpuRelationshipDO.setUnitName(CommodityMaterialSpuRelationshipDto.getUnitName());

            commoditySupplySpuRelationshipMapper.insert(commodityMaterialSpuRelationshipDO);
        }

        //保存商品spu图片信息
        List<GoodsPictureDTO> goodsImage = goodsDto.getGoodsPicture();
        for (GoodsPictureDTO goodsPictureDto : goodsImage) {
            GoodsPictureDO goodsPicture = new GoodsPictureDO();
            goodsPicture.setGoodsId(goods.getId());
            goodsPicture.setGoodsImage(goodsPictureDto.getGoodsImage());
            goodsPicture.setIsDefault(goodsPictureDto.getIsDefault());
            goodsPictureMapper.insert(goodsPicture);
        }

        //保存商品spu供应商信息
        SupplierDO supplier = new SupplierDO();
        supplier.setSupplyId(goodsDto.getSupplyId());
        supplier.setSupplierCompanyName(goodsDto.getSupplier());
        supplier.setGoodsId(goods.getId());
        supplier.setCreateTime(localDateTime);
        supplier.setUpdateTime(localDateTime);
        supplier.setCreater(userName);
        supplier.setModifier(userName);
        supplierMapper.insert(supplier);

        //商品spu和税收对应关系VO值对象
        GoodsTaxDO goodsTax = new GoodsTaxDO();
        goodsTax.setSpuId(goods.getId());
        goodsTax.setTaxCode(goodsDto.getGoodsTax().getTaxCode());
        goodsTax.setTaxRate(goodsDto.getGoodsTax().getTaxRate());
        goodsTax.setCreateTime(localDateTime);
        goodsTax.setUpdateTime(localDateTime);
        goodsTaxMapper.insert(goodsTax);

        for (GoodsSkuDTO goodsSkuDto : goodsSkuDtos) {
            GoodsSkuDO goodsSku = convertGoodsSkuDto2Do(goodsSkuDto);
            goodsSku.setGoodsId(goods.getId());
            long skuSnowId = IdUtil.getSnowflake(getWorkId(), getDataCenterId()).nextId();
            goodsSku.setSkuCode(SKU_PREFIX + skuSnowId);
            goodsSku.setCreateTime(localDateTime);
            goodsSku.setUpdateTime(localDateTime);
            goodsSku.setCreater(userName);
            goodsSku.setModifier(userName);

            //保存商品sku的规格和值
            List<GoodsSkuPropertyValueDTO> goodsSkuPropertyValues = goodsSkuDto.getGoodsSkuPropertyValue();
            StringBuilder skuNameBuilder = new StringBuilder();

            if (goodsDto.getGoodsType().equals(GoodsType.COMPOSE)) {
                goodsSku.setGoodsName(goods.getGoodsName());
            } else {
                for (GoodsSkuPropertyValueDTO goodsSkuPropertyValue : goodsSkuPropertyValues) {
                    GoodsSkuPropertyValueDO skuPropertyValue = new GoodsSkuPropertyValueDO();
                    skuNameBuilder.append(goodsSkuPropertyValue.getPropertyValueName()).append(" ");
                }
                goodsSku.setGoodsName(goods.getGoodsName() + " " + skuNameBuilder.toString().trim());
            }
            goodsSkuMapper.insert(goodsSku);

            goodsSkuDto.setId(goodsSku.getId());
            goodsSkuDto.setSkuCode(goodsSku.getSkuCode());
            goodsSkuDto.setGoodsId(goods.getId());
            goodsSkuDto.setGoodsType(goods.getGoodsType());

            for (GoodsSkuPropertyValueDTO goodsSkuPropertyValue : goodsSkuPropertyValues) {
                GoodsSkuPropertyValueDO skuPropertyValue = new GoodsSkuPropertyValueDO();
                skuPropertyValue.setGoodsSkuId(goodsSku.getId());
                skuPropertyValue.setMaterialSkuId(goodsSku.getMaterialSkuId());

                if (goodsSkuPropertyValue.getPropertyId() == null) {
                    long propertyId = IdUtil.getSnowflake(getWorkId(), getDataCenterId()).nextId();
                    skuPropertyValue.setPropertyId(propertyId);
                } else {
                    skuPropertyValue.setPropertyId(goodsSkuPropertyValue.getPropertyId());
                }
                skuPropertyValue.setPropertyName(goodsSkuPropertyValue.getPropertyName());
                if (goodsSkuPropertyValue.getPropertyValueId() == null) {
                    long propertyValueId = IdUtil.getSnowflake(getWorkId(), getDataCenterId()).nextId();
                    skuPropertyValue.setPropertyValueId(propertyValueId);
                } else {
                    skuPropertyValue.setPropertyValueId(goodsSkuPropertyValue.getPropertyValueId());
                }
                skuPropertyValue.setPropertyValueName(goodsSkuPropertyValue.getPropertyValueName());
                skuPropertyValue.setCreateTime(localDateTime);
                skuPropertyValue.setUpdateTime(localDateTime);
                goodsSkuPropertyValueMapper.insert(skuPropertyValue);
            }

            //保存组合商品和物料的sku对应关系
            List<CommodityMaterialSkuRelationshipDTO> commoditySupplySkuRelationshipDtos
                    = goodsSkuDto.getCommodityMaterialSkuRelationship();
            for (CommodityMaterialSkuRelationshipDTO commoditySupplySkuRelationshipDto : commoditySupplySkuRelationshipDtos) {
                commoditySupplySkuRelationshipDto.setCreateTime(localDateTime);
                commoditySupplySkuRelationshipDto.setUpdateTime(localDateTime);
                commoditySupplySkuRelationshipDto.setSkuId(goodsSku.getId());
                commoditySupplySkuRelationshipDto.setSpuId(goods.getId());
                CommodityMaterialSkuRelationshipDO commoditySupplySkuRelationship
                        = convertCommoditySupplySkuRelationshipDto2Do(commoditySupplySkuRelationshipDto);
                commoditySupplySkuRelationshipMapper.insert(commoditySupplySkuRelationship);
            }
        }

        if (goodsDto.getGoodsState().equals(GoodsStatus.FIX_PUTTED_ON_SHELVES.getCode())) {
            GoodsScheduleDO goodsSchedule = new GoodsScheduleDO();
            goodsSchedule.setGoodsId(goods.getId());
            goodsSchedule.setGoodsSelltime(LocalDateTime.parse(goodsDto.getGoodsSelltime(), DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS)));
            goodsSchedule.setIsSuccess(numberZero);
            goodsSchedule.setIsSchedule(numberZero);
            goodsScheduleMapper.insert(goodsSchedule);

            ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
            LocalDateTime date = LocalDateTime.parse(goodsDto.getGoodsSelltime(), DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
            executor.schedule(
                    () -> {
                        //调起任务
                        goodsSchedule.setIsSchedule(NumberConstant.NUMBER_ONE.intValue());
                        goodsScheduleMapper.updateById(goodsSchedule);

                        LambdaUpdateWrapper<GoodsDO> updateWrapper = new LambdaUpdateWrapper<>();
                        updateWrapper.set(GoodsDO::getUpdateTime, LocalDateTime.now())
                                .set(GoodsDO::getGoodsState, GoodsStatus.PUTTED_ON_SHELVES.getCode())
                                .eq(GoodsDO::getId, goods.getId());
                        int update = goodsMapper.update(new GoodsDO(), updateWrapper);

                        if (update > NumberConstant.NUMBER_ZERO.intValue()) {
                            if (redisCache.hasObjectByKey(GoodsKeyConstant.GOODS_DETAIL_KEY + goods.getId())) {
                                redisCache.deleteObject(GoodsKeyConstant.GOODS_DETAIL_KEY + goods.getId());
                            }

                            goodsSchedule.setIsSuccess(NumberConstant.NUMBER_ONE.intValue());
                            goodsScheduleMapper.updateById(goodsSchedule);
                        }
                    },
                    LocalDateTime.now().until(date, ChronoUnit.MILLIS),
                    TimeUnit.MILLISECONDS);
            executor.shutdown();
        }

        for (GoodsSkuDTO goodsSkuDto : goodsSkuDtos) {
            SkuDTO skuDto = new SkuDTO();
            skuDto.setId(goodsSkuDto.getId());
            skuDto.setGoodsId(goodsSkuDto.getGoodsId());
            StringBuilder skuNameBuilder = new StringBuilder();

            //保存商品sku的规格和值
            List<GoodsSkuPropertyValueDTO> goodsSkuPropertyValues = goodsSkuDto.getGoodsSkuPropertyValue();
            if (goodsDto.getGoodsType().equals(GoodsType.COMPOSE)) {
                skuDto.setGoodsName(goods.getGoodsName());
            } else {
                for (GoodsSkuPropertyValueDTO goodsSkuPropertyValue : goodsSkuPropertyValues) {
                    skuNameBuilder.append(goodsSkuPropertyValue.getPropertyValueName()).append(" ");
                }
                skuDto.setGoodsName(goods.getGoodsName() + " " + skuNameBuilder.toString().trim());
            }
            skuDto.setSpecName(goodsSkuDto.getSpecName());
            skuDto.setGoodsPropertyImage(goodsSkuDto.getGoodsPropertyImage());
            skuDto.setSupplyId(goodsSkuDto.getSupplyId());
            skuDto.setGoodsPrice(goodsSkuDto.getGoodsPrice());
            skuDto.setPlatinumPrice(goodsSkuDto.getPlatinumPrice());
            skuDto.setDiamondsPrice(goodsSkuDto.getDiamondsPrice());
            skuDto.setKingPrice(goodsSkuDto.getKingPrice());
            skuDto.setGetOrderPrice(goodsSkuDto.getGetOrderPrice());
            skuDto.setGoodsCostprice(goodsSkuDto.getGoodsCostprice());
            skuDto.setGoodsGrossWeight(goodsSkuDto.getWeight());
            skuDto.setCateId(goodsSkuDto.getCateId());
            GoodsDO goodsDo = goodsMapper.selectById(skuDto.getGoodsId());
            FreightTempDTO freightTempDTO = freightInfo(goodsDo.getTransportId());
            skuDto.setFreightTempDTO(freightTempDTO);
            skuDto.setGoodsType(goodsDo.getGoodsType());
            skuDto.setDrainage(goodsDo.getIsYinliu());
            skuDto.setIsImport(goodsDo.getIsImport());
            skuDto.setGoodCountry(goodsDo.getGoodCountry());
            skuDto.setFixRebate(goodsDo.getFixRebate());
            skuDto.setNoDeliveryRegion(goodsDo.getNoDeliveryRegionId());
            redisCache.setCacheObject(GoodsKeyConstant.GOODS_SKU_KEY + skuDto.getId(), skuDto);
        }


        return goodsSkuDtos;
    }


    private void checkGoods(GoodsDTO goodsDto) {
        List<Object> goodsIdList = goodsMapper.selectObjs(
                Wrappers.<GoodsDO>lambdaQuery()
                        .select(GoodsDO::getId)
                        .eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .eq(GoodsDO::getGoodsName, goodsDto.getGoodsName()));

        if (goodsIdList.size() > NumberConstant.NUMBER_ZERO.intValue()) {
            throw new BusinessException(GoodsEnum.GOODS_HAS_EXISTED);
        }
    }

    /**
     * 更新商品
     *
     * @param goodsDto 商品
     * @param request  request
     * @return List<GoodsSkuDTO> sku DTO集合
     */
    @Override
    public List<GoodsSkuDTO> updateGoods(GoodsDTO goodsDto, HttpServletRequest request) {
        //更新商品spu基本信息
        GoodsDO goods = convertGoodsDto2Do(goodsDto);
        LocalDateTime localDateTime = LocalDateTime.now();
        goods.setUpdateTime(localDateTime);
        String userName = request.getHeader(RequestConstant.ADMIN_NAME);
        goods.setModifier(userName);

        List<GoodsSkuDTO> goodsSkuDtos = goodsDto.getGoodsSkus();
        goodsSkuDtos.sort((x, y) -> Double.compare(x.getGoodsPrice().doubleValue(), y.getGoodsPrice().doubleValue()));
        int numberZero = NumberConstant.NUMBER_ZERO.intValue();
        goods.setGoodsPrice(goodsSkuDtos.get(numberZero).getGoodsPrice());
        goods.setGoodsMarketprice(goodsSkuDtos.get(numberZero).getGoodsMarketprice());
        goodsMapper.updateById(goods);

        if (goods.getGoodsType().equals(GoodsType.THIRD_PARTY)) {
            GoodsTaxDO goodsTax = new GoodsTaxDO();
            goodsTax.setId(goodsDto.getGoodsTax().getId());
            goodsTax.setSpuId(goods.getId());
            goodsTax.setTaxCode(goodsDto.getGoodsTax().getTaxCode());
            goodsTax.setTaxRate(goodsDto.getGoodsTax().getTaxRate());
            goodsTax.setUpdateTime(localDateTime);
            goodsTaxMapper.updateById(goodsTax);
        }

        //更新商品spu的图片基本信息
        int result = goodsPictureMapper.delete(new QueryWrapper<GoodsPictureDO>().eq("goods_id", goods.getId()));
        if (result > NumberConstant.NUMBER_ZERO.intValue()) {
            //保存商品spu图片信息
            List<GoodsPictureDTO> goodsImage = goodsDto.getGoodsPicture();
            for (GoodsPictureDTO goodsPictureDto : goodsImage) {
                GoodsPictureDO goodsPicture = new GoodsPictureDO();
                goodsPicture.setGoodsId(goods.getId());
                goodsPicture.setGoodsImage(goodsPictureDto.getGoodsImage());
                goodsPicture.setIsDefault(goodsPictureDto.getIsDefault());
                goodsPictureMapper.insert(goodsPicture);
            }
        }

        List<GoodsSkuDO> goodsSkusList = convertGoodsSkuDtoList2DoList(goodsSkuDtos);

        LambdaQueryWrapper<GoodsSkuDO> goodsSkuWrapper = Wrappers.lambdaQuery();
        goodsSkuWrapper.eq(GoodsSkuDO::getGoodsId, goods.getId());
        goodsSkuWrapper.eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        List<GoodsSkuDO> goodsSkus = goodsSkuMapper.selectList(goodsSkuWrapper);

        List<GoodsSkuDO> distinctByUniqueList = goodsSkus.stream()
                //goodsSkus - goodsSkusList 差集
                .filter(item -> !goodsSkusList.stream().map(GoodsSkuDO::getId)
                        .collect(Collectors.toList())
                        .contains(item.getId())).collect(toList());

        for (GoodsSkuDO goodsSku : distinctByUniqueList) {
            goodsSku.setIsDel(StatusEnum.STATUS_YES.getCode());
            goodsSku.setUpdateTime(localDateTime);
            goodsSku.setModifier(userName);
            goodsSkuMapper.updateById(goodsSku);
        }

        for (GoodsSkuDTO goodsSkuDto : goodsSkuDtos) {
            GoodsSkuDO goodsSku = convertGoodsSkuDto2Do(goodsSkuDto);
            goodsSku.setGoodsId(goods.getId());
            goodsSku.setUpdateTime(localDateTime);
            goodsSku.setModifier(userName);
            goodsSkuDto.setGoodsType(goods.getGoodsType());
            goodsSkuDto.setGoodsId(goods.getId());
            List<GoodsSkuPropertyValueDTO> goodsSkuPropertyValues = goodsSkuDto.getGoodsSkuPropertyValue();
            StringBuilder skuNameBuilder = new StringBuilder();

            if (goodsDto.getGoodsType().equals(GoodsType.COMPOSE)) {
                goodsSku.setGoodsName(goods.getGoodsName());
            } else {
                for (GoodsSkuPropertyValueDTO goodsSkuPropertyValue : goodsSkuPropertyValues) {
                    GoodsSkuPropertyValueDO skuPropertyValue = new GoodsSkuPropertyValueDO();
                    skuNameBuilder.append(goodsSkuPropertyValue.getPropertyValueName()).append(" ");
                }
                goodsSku.setGoodsName(goods.getGoodsName() + " " + skuNameBuilder.toString().trim());
            }

            if (goodsSku.getId() == null) {
                long skuSnowId = IdUtil.getSnowflake(getWorkId(), getDataCenterId()).nextId();
                goodsSku.setSkuCode(SKU_PREFIX + skuSnowId);
                goodsSku.setCreateTime(localDateTime);
                goodsSku.setCreater(userName);
                goodsSkuMapper.insert(goodsSku);
            } else {
                goodsSku.setIsDel(NumberConstant.NUMBER_ZERO.intValue());
                goodsSkuMapper.updateById(goodsSku);
            }

            for (GoodsSkuPropertyValueDTO goodsSkuPropertyValue : goodsSkuPropertyValues) {
                GoodsSkuPropertyValueDO skuPropertyValue = new GoodsSkuPropertyValueDO();
                skuPropertyValue.setId(goodsSkuPropertyValue.getId());
                skuPropertyValue.setGoodsSkuId(goodsSku.getId());
                skuPropertyValue.setPropertyId(goodsSkuPropertyValue.getPropertyId());
                skuPropertyValue.setPropertyName(goodsSkuPropertyValue.getPropertyName());
                skuPropertyValue.setPropertyValueId(goodsSkuPropertyValue.getPropertyValueId());
                skuPropertyValue.setPropertyValueName(goodsSkuPropertyValue.getPropertyValueName());
                skuPropertyValue.setUpdateTime(localDateTime);
                goodsSkuPropertyValueMapper.updateById(skuPropertyValue);
            }

            if (goods.getGoodsType().equals(GoodsType.COMPOSE)) {
                //更新组合商品和物料的sku对应关系
                List<CommodityMaterialSkuRelationshipDTO> commoditySupplySkuRelationshipDtos
                        = goodsSkuDto.getCommodityMaterialSkuRelationship();
                for (CommodityMaterialSkuRelationshipDTO commoditySupplySkuRelationshipDto : commoditySupplySkuRelationshipDtos) {
                    LambdaUpdateWrapper<CommodityMaterialSkuRelationshipDO> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.set(CommodityMaterialSkuRelationshipDO::getUpdateTime, localDateTime)
                            .set(CommodityMaterialSkuRelationshipDO::getComposeNumber, commoditySupplySkuRelationshipDto.getComposeNumber())
                            .eq(CommodityMaterialSkuRelationshipDO::getId, commoditySupplySkuRelationshipDto.getId());
                    commoditySupplySkuRelationshipMapper.update(new CommodityMaterialSkuRelationshipDO(), updateWrapper);
                }
            }
        }

        if (goodsDto.getGoodsState().equals(GoodsStatus.FIX_PUTTED_ON_SHELVES.getCode())) {
            GoodsScheduleDO goodsSchedule = new GoodsScheduleDO();
            goodsSchedule.setGoodsId(goods.getId());
            goodsSchedule.setGoodsSelltime(LocalDateTime.parse(goodsDto.getGoodsSelltime(), DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS)));
            goodsSchedule.setIsSuccess(numberZero);
            goodsSchedule.setIsSchedule(numberZero);
            goodsScheduleMapper.insert(goodsSchedule);

            ScheduledExecutorService exe = Executors.newSingleThreadScheduledExecutor();
            LocalDateTime date = LocalDateTime.parse(goodsDto.getGoodsSelltime(), DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
            exe.schedule(
                    () -> {
                        //调起任务
                        goodsSchedule.setIsSchedule(NumberConstant.NUMBER_ONE.intValue());
                        goodsScheduleMapper.updateById(goodsSchedule);

                        LambdaUpdateWrapper<GoodsDO> updateWrapper = new LambdaUpdateWrapper<>();
                        updateWrapper.set(GoodsDO::getUpdateTime, LocalDateTime.now())
                                .set(GoodsDO::getGoodsState, GoodsStatus.PUTTED_ON_SHELVES.getCode())
                                .eq(GoodsDO::getId, goods.getId());
                        int update = goodsMapper.update(new GoodsDO(), updateWrapper);

                        if (update > NumberConstant.NUMBER_ZERO.intValue()) {
                            if (redisCache.hasObjectByKey(GoodsKeyConstant.GOODS_DETAIL_KEY + goods.getId())) {
                                redisCache.deleteObject(GoodsKeyConstant.GOODS_DETAIL_KEY + goods.getId());
                            }

                            goodsSchedule.setIsSuccess(NumberConstant.NUMBER_ONE.intValue());
                            goodsScheduleMapper.updateById(goodsSchedule);
                        }
                    },
                    LocalDateTime.now().until(date, ChronoUnit.MILLIS),
                    TimeUnit.MILLISECONDS);
            exe.shutdown();
        }

        for (GoodsSkuDTO goodsSkuDto : goodsSkuDtos) {
            SkuDTO skuDto = new SkuDTO();
            skuDto.setId(goodsSkuDto.getId());
            skuDto.setGoodsId(goodsSkuDto.getGoodsId());
            List<GoodsSkuPropertyValueDTO> goodsSkuPropertyValues = goodsSkuDto.getGoodsSkuPropertyValue();
            StringBuilder skuNameBuilder = new StringBuilder();

            if (goodsDto.getGoodsType().equals(GoodsType.COMPOSE)) {
                skuDto.setGoodsName(goods.getGoodsName());
            } else {
                for (GoodsSkuPropertyValueDTO goodsSkuPropertyValue : goodsSkuPropertyValues) {
                    skuNameBuilder.append(goodsSkuPropertyValue.getPropertyValueName()).append(" ");
                }
                skuDto.setGoodsName(goods.getGoodsName() + " " + skuNameBuilder.toString().trim());
            }
            skuDto.setSpecName(goodsSkuDto.getSpecName());
            skuDto.setGoodsPropertyImage(goodsSkuDto.getGoodsPropertyImage());
            skuDto.setSupplyId(goodsSkuDto.getSupplyId());
            skuDto.setGoodsPrice(goodsSkuDto.getGoodsPrice());
            skuDto.setPlatinumPrice(goodsSkuDto.getPlatinumPrice());
            skuDto.setDiamondsPrice(goodsSkuDto.getDiamondsPrice());
            skuDto.setKingPrice(goodsSkuDto.getKingPrice());
            skuDto.setGetOrderPrice(goodsSkuDto.getGetOrderPrice());
            skuDto.setGoodsCostprice(goodsSkuDto.getGoodsCostprice());
            skuDto.setGoodsGrossWeight(goodsSkuDto.getWeight());
            skuDto.setCateId(goodsSkuDto.getCateId());
            GoodsDO goodsDo = goodsMapper.selectById(skuDto.getGoodsId());
            FreightTempDTO freightTempDTO = freightInfo(goodsDo.getTransportId());
            skuDto.setFreightTempDTO(freightTempDTO);
            skuDto.setGoodsType(goodsDo.getGoodsType());
            skuDto.setDrainage(goodsDo.getIsYinliu());
            skuDto.setIsImport(goodsDo.getIsImport());
            skuDto.setGoodCountry(goodsDo.getGoodCountry());
            skuDto.setFixRebate(goodsDo.getFixRebate());
            //不发货地区
            skuDto.setNoDeliveryRegion(goodsDo.getNoDeliveryRegionId());
            redisCache.setCacheObject(GoodsKeyConstant.GOODS_SKU_KEY + skuDto.getId(), skuDto);
        }

        return goodsSkuDtos;
    }

    /**
     * 执行上架操作
     *
     * @param goodsId 商品id
     * @return 处理结果
     */
    @Override
    public Boolean putOnShelves(Long goodsId, HttpServletRequest request) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(goodsId == null);
        GoodsDTO goods = convertGoodsDo2Dto(goodsMapper.selectById(goodsId));

        if (!goodsStateManager.canPutOnShelves(goods)) {
            return Boolean.FALSE;
        }
        goods.setModifier(request.getHeader(RequestConstant.ADMIN_NAME));
        goodsStateManager.putOnShelves(goods);

        if (goods.getGoodsState().equals(GoodsStatus.FIX_PUTTED_ON_SHELVES.getCode())) {
            goodsScheduleMapper.delete(Wrappers.<GoodsScheduleDO>lambdaQuery()
                    .eq(GoodsScheduleDO::getGoodsId, goodsId));
        }
        return Boolean.TRUE;
    }

    /**
     * 执行下架操作
     *
     * @param goodsId 商品id
     * @return 处理结果
     */
    @Override
    public Boolean pullOffShelves(Long goodsId, HttpServletRequest request) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(goodsId == null);
        GoodsDTO goods = convertGoodsDo2Dto(goodsMapper.selectById(goodsId));

        if (!goodsStateManager.canPullOffShelves(goods)) {
            return Boolean.FALSE;
        }
        goods.setModifier(request.getHeader(RequestConstant.ADMIN_NAME));
        goodsStateManager.pullOffShelves(goods);
        return Boolean.TRUE;
    }

    /**
     * 删除商品
     *
     * @param goodsId 商品id
     */
    @Override
    public void deleteGoods(String goodsId, HttpServletRequest request) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(goodsId == null);

        String[] goodsIds = goodsId.split(",");

        //存在批量操作商品
        Arrays.stream(goodsIds).forEach(gid-> {
            //校验是否活动商品
            if (redisCache.hasObjectByKey(GoodsKeyConstant.EXCELLENT_ACTIVITY_GOODS + gid)) {
                throw new BusinessException(GoodsEnum.EXCELLENT_ACTIVITY_GOODS_EXIST);
            }
            if (redisCache.hasObjectByKey(GoodsKeyConstant.YOUXUAN_ACTIVITY_GOODS + gid)) {
                throw new BusinessException(GoodsEnum.YOUXUAN_ACTIVITY_GOODS_EXIST);
            }
            if (redisCache.hasObjectByKey(GoodsKeyConstant.SMALL_SHOP_ACTIVITY + gid)) {
                throw new BusinessException(GoodsEnum.SMALL_SHOP_ACTIVITY_EXIST);
            }
            if (redisCache.hasObjectByKey(GoodsKeyConstant.RECOMMOND_ACTIVITY_GOODS + gid)) {
                DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                //今日推荐判断活动结束时间
                String obj = redisCache.getCacheObject(GoodsKeyConstant.RECOMMOND_ACTIVITY_GOODS + gid);
                LocalDateTime end = LocalDateTime.from(dtf.parse(obj));
                if(LocalDateTime.now().isBefore(end)) {
                    throw new BusinessException(GoodsEnum.RECOMMOND_ACTIVITY_GOODS_EXIST);
                }
            }
            if (redisCache.hasObjectByKey(GoodsKeyConstant.PURCHASELIMIT_ACTIVITY + gid)) {
                throw new BusinessException(GoodsEnum.PURCHASELIMIT_ACTIVITY_EXIST);
            }
            if (redisCache.hasObjectByKey(GoodsKeyConstant.POSTAGE_GOODS_ACTIVITY + gid)) {
                throw new BusinessException(GoodsEnum.POSTAGE_GOODS_ACTIVITY_EXIST);
            }
        });
        List<GoodsDO> goodsList = goodsMapper.selectList(
                Wrappers.<GoodsDO>lambdaQuery()
                        .select(GoodsDO::getGoodsState)
                        .eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .apply("id in (" + goodsId + ")"));

        for (GoodsDO goods : goodsList) {
            if (goods.getGoodsState().equals(GoodsStatus.PUTTED_ON_SHELVES.getCode())) {
                throw new BusinessException(GoodsEnum.GOODS_STATUS_ABLED);
            } else if (goods.getGoodsState().equals(GoodsStatus.FIX_PUTTED_ON_SHELVES.getCode())) {
                throw new BusinessException(GoodsEnum.GOODS_STATUS_ABLED_FIXED);
            }
        }

        LambdaUpdateWrapper<GoodsDO> goodsUpdateWrapper = new LambdaUpdateWrapper<>();
        goodsUpdateWrapper.set(GoodsDO::getIsDel, StatusEnum.STATUS_YES.getCode())
                .set(GoodsDO::getUpdateTime, LocalDateTime.now())
                .set(GoodsDO::getModifier, request.getHeader(RequestConstant.ADMIN_NAME))
                .in(GoodsDO::getId, Arrays.asList(goodsId.split(",")));
        goodsMapper.update(new GoodsDO(), goodsUpdateWrapper);

        LambdaUpdateWrapper<GoodsSkuDO> goodsSkuUpdateWrapper = new LambdaUpdateWrapper<>();
        goodsSkuUpdateWrapper.set(GoodsSkuDO::getIsDel, StatusEnum.STATUS_YES.getCode())
                .set(GoodsSkuDO::getUpdateTime, LocalDateTime.now())
                .set(GoodsSkuDO::getModifier, request.getHeader(RequestConstant.ADMIN_NAME))
                .in(GoodsSkuDO::getGoodsId, Arrays.asList(goodsId.split(",")));
        goodsSkuMapper.update(new GoodsSkuDO(), goodsSkuUpdateWrapper);
    }

    /**
     * 添加库存 - 获取sku列表
     *
     * @param id 商品主键id
     * @return
     */
    @Override
    public List<GoodsSkuStockDTO> skuStockList(Long id) {
        GoodsDO goods = goodsMapper.selectById(id);
        ExceptionEnum.FAIL_GOODS_EXIST.doThrowIf(goods == null);
        //获取sku信息
        List<GoodsSkuDO> skus = goodsSkuMapper.selectList(
                Wrappers.<GoodsSkuDO>lambdaQuery()
                        .eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .eq(GoodsSkuDO::getGoodsId, id));
        List<GoodsSkuStockDTO> list = skus.stream().map(sku -> {
            GoodsSkuStockDTO dto = new GoodsSkuStockDTO();
            dto.setId(sku.getGoodsId());
            dto.setSkuId(sku.getId());
            dto.setSkuCode(sku.getSkuCode());
            dto.setMaterialSkuId(sku.getMaterialSkuId());
            dto.setMaterialSkuCode(sku.getMaterialSkuCode());
            dto.setWeight(sku.getWeight());
            dto.setGoodsName(sku.getGoodsName());
            dto.setGoodsType(goods.getGoodsType());
            return dto;
        }).collect(Collectors.toList());
        return list;
    }

    /**
     * 清除库存
     *
     * @param id 商品skuid
     */
    @Override
    public ClearSkuMaterialDTO clearInventory(Long id) {
        ExceptionEnum.FAIL_SKU_SUPPLY.doThrowIf(id == null);
        GoodsDO goods = goodsMapper.selectById(id);
        ExceptionEnum.FAIL_GOODS_EXIST.doThrowIf(goods == null);
        return packClearDto(goods);
    }

    @Override
    public IPage<GoodsDO> goodsListByCategoryId(Long categoryId, Integer page, Integer size) {
        ExceptionEnum.FAIL_GOODS_CATEGORY_ID_NULL.doThrowIf(categoryId == null);
        //分页/分类id/未删除/已上架
        IPage<GoodsDO> pageInfo = goodsMapper.selectPage(new Page<>(page, size),
                Wrappers.<GoodsDO>lambdaQuery()
                        .eq(GoodsDO::getCreatgroyFirst, categoryId)
                        .eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .eq(GoodsDO::getGoodsState, StatusEnum.STATUS_YES.getCode()));
        return pageInfo;
    }

    /**
     * 获取sku的物料id集合
     *
     * @param id spuid
     * @return
     */
    @Override
    public List<Long> selectSkuIdsBySpuId(Long id) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(id == null);
        //获取sku信息
        List<Object> skus = goodsSkuMapper.selectObjs(
                Wrappers.<GoodsSkuDO>lambdaQuery()
                        .select(GoodsSkuDO::getMaterialSkuId)
                        .eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .eq(GoodsSkuDO::getGoodsId, id));
        ExceptionEnum.FAIL_GOODS_SKU_EXIST.doThrowIf(skus.size() == NumberConstant.NUMBER_ZERO);
        List<Long> ids = (List<Long>) (List) skus;
        return ids;
    }

    /**
     * 封装供应链接口dto
     *
     * @param commodityApplyDTO 供应链dto
     * @param vo                sku库存信息
     * @return
     */
    @Override
    public CommodityApplyDTO encapsulationStock(CommodityApplyDTO commodityApplyDTO, SkuSupplyAddVO vo) {
        //获取spu信息
        GoodsDO goods = goodsMapper.selectById(vo.getId());
        ExceptionEnum.FAIL_GOODS_EXIST.doThrowIf(goods == null);
        commodityApplyDTO.setSpuId(goods.getId());
        commodityApplyDTO.setSpuCode(goods.getSpuCode());
        commodityApplyDTO.setSpuName(goods.getGoodsName());
        //封装sku的信息
        List<GoodsSkuStockVO> skus = vo.getList();
        ExceptionEnum.FAIL_GOODS_SKU_EXIST.doThrowIf(skus.size() == NumberConstant.NUMBER_ZERO);
        //添加sku信息
        List<CommodityApplyDetailDTO> details = new ArrayList<>();
        //sku物料信息
        List<CommodityApplyMaterialDTO> materials = new ArrayList<>();
        //按组合商品/单一商品封装对应关系
        if (GoodsType.COMPOSE.equals(goods.getGoodsType())) {
            thirdGoodsMaterialList(skus, details, materials);
        } else {
            notThirdGoodsMaterialList(skus, details, materials);
        }
        commodityApplyDTO.setDetails(details);
        commodityApplyDTO.setMaterials(materials);
        return commodityApplyDTO;
    }

    /**
     * 查询商品信息
     *
     * @param ids supid
     * @return 商品DTO值对象集合
     */
    @Override
    public List<GoodsDTO> goodsListBySpuId(List<Long> ids) {
        return convertGoodsDoList2DtoList(goodsMapper.selectList(
                Wrappers.<GoodsDO>lambdaQuery()
                        .in(GoodsDO::getId, ids)));
    }

    /**
     * 查询商品信息
     *
     * @param goodsName 商品名
     * @return 商品DTO值对象集合
     */
    @Override
    public List<GoodsDTO> searchGoodsByGoodsNameDrop(String goodsName) {
        QueryWrapper<GoodsDO> goodsWrapper = new QueryWrapper();
        goodsWrapper.eq("is_del", StatusEnum.STATUS_NO.getCode());
        List<GoodsDO> goodsList = goodsMapper.selectList(goodsWrapper);
        List<CategoryDO> categoryDOS = categoryMapper.selectList(
                Wrappers.<CategoryDO>lambdaQuery()
                        .eq(CategoryDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .eq(CategoryDO::getStatus, StatusEnum.STATUS_YES.getCode()));
        return goodsList.stream().map(po -> {
            GoodsDTO dto = convertGoodsDo2Dto(po);
            CategoryDO ca = categoryDOS.stream().filter(d -> d.getId().equals(po.getCreatgroyFirst())).findAny().orElse(null);
            if (ca != null) {
                dto.setCreatgroyName(ca.getCategoryName());
            }
            return dto;
        }).collect(Collectors.toList());
    }


    /**
     * 查询组合商品的物料信息
     *
     * @param id spuid
     * @return
     */
    @Override
    public GoodsMateriaDTO selectCombinationSkuIdsBySpuId(Long id) {
        //组合商品获取唯一的sku信息
        GoodsSkuDO skuDO = goodsSkuMapper.selectOne(
                Wrappers.<GoodsSkuDO>lambdaQuery()
                        .eq(GoodsSkuDO::getGoodsId, id)
                        .eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode()));
        ExceptionEnum.FAIL_GOODS_SKU_EXIST.doThrowIf(skuDO == null);
        //获取商品的spu物料信息
        List<CommodityMaterialSpuRelationshipDO> materialSpuRelationships = commoditySupplySpuRelationshipMapper.selectList(
                Wrappers.<CommodityMaterialSpuRelationshipDO>lambdaQuery()
                        .eq(CommodityMaterialSpuRelationshipDO::getSpuId, id));
        ExceptionEnum.FAIL_GOODS_SPU_MATERIA_EXIST.doThrowIf(CollectionUtil.isEmpty(materialSpuRelationships));
        //过滤取出所有的spu物料id
        List<Long> materialSpuIds = materialSpuRelationships.stream().map(m -> {
            return m.getMaterialSpuId();
        }).collect(Collectors.toList());
        //根据商品的skuid和spu物料id获取 sku的物料信息
        List<CommodityMaterialSkuRelationshipDO> materialSkuRelationships = commoditySupplySkuRelationshipMapper.selectList(
                Wrappers.<CommodityMaterialSkuRelationshipDO>lambdaQuery()
                        .eq(CommodityMaterialSkuRelationshipDO::getSkuId, skuDO.getId())
                        .in(CommodityMaterialSkuRelationshipDO::getMaterialSpuId, materialSpuIds));
        ExceptionEnum.FAIL_GOODS_SKU_MATERIA_EXIST.doThrowIf(CollectionUtil.isEmpty(materialSkuRelationships));
        return getGoodsMateriaCompose(materialSpuRelationships, materialSkuRelationships);
    }

    /**
     * 获取商品的sku信息及id集合
     *
     * @param spuId 商品spuid
     * @return
     */
    @Override
    public GoodsSkuStockIdDTO getGoodsSkuAndIdsBySpuId(Long spuId) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(spuId == null);
        List<GoodsSkuDO> skuDOS = goodsSkuMapper.selectList(
                Wrappers.<GoodsSkuDO>lambdaQuery()
                        .eq(GoodsSkuDO::getGoodsId, spuId)
                        .eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode()));
        ExceptionEnum.FAIL_GOODS_SKU_EXIST.doThrowIf(CollectionUtil.isEmpty(skuDOS));
        return getGoodsSkuStockWares(skuDOS);
    }

    /**
     * 订单-预售转真实业务日志
     *
     * @param log
     */
    @Override
    public void addPre2RealStockLog(OrderStockLog log) {
        log.setOperationTime(LocalDateTime.now());
        log.setOperation(InventoryStatus.ORDER_ADD_STOCK_MSG + log.getAddStockNum());
        orderStockLogMapper.insert(log);
    }

    /**
     * 预售转真实 日志列表
     *
     * @param page
     * @param log
     * @return
     */
    @Override
    public IPage<OrderStockLog> stockLogPage(Page page, OrderStockLog log) {
        QueryWrapper<OrderStockLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(log.getSpuId() != null, "spu_id", log.getSpuId());
        queryWrapper.eq(StringUtils.isNotEmpty(log.getOperationUser()), "operation_user", log.getOperationUser());
        queryWrapper.orderByDesc("operation_time");
        return orderStockLogMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<GoodsShowDTO> releaseListGoods(GoodsQuery goodsQuery) {
        LambdaQueryWrapper<GoodsDO> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotEmpty(goodsQuery.getGoodsName()), GoodsDO::getGoodsName, goodsQuery.getGoodsName());
        wrapper.eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        wrapper.eq(GoodsDO::getGoodsState, StatusEnum.STATUS_YES.getCode());
        List<GoodsDO> goodsList = goodsMapper.selectList(wrapper);
        List<GoodsShowDTO> goodsShows = new ArrayList<>(goodsList.size());

        for (GoodsDO goods : goodsList) {
            GoodsShowDTO goodsShow = new GoodsShowDTO();
            goodsShow.setGoodsId(goods.getId());
            goodsShow.setGoodsImage(goods.getGoodsImage());
            goodsShow.setGoodsName(goods.getGoodsName());
            goodsShows.add(goodsShow);
        }
        return goodsShows;
    }

    /**
     * 商品列表页面获取厂家名称下拉列表
     *
     * @return 厂家名称列表
     */
    @Override
    public List<SupplierDTO> listSupplier() {
        QueryWrapper<SupplierDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT supply_id,supplier_company_name,status,is_del").orderByAsc("supply_id")
                .lambda()
                .eq(SupplierDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                .eq(SupplierDO::getStatus, StatusEnum.STATUS_YES.getCode());

        List<SupplierDO> suppliers = supplierMapper.selectList(queryWrapper);
        return convertSupplierDoList2DtoList(suppliers);
    }

    /**
     * 获取定时上架调度的商品
     *
     * @return 定时上架调度的商品列表
     */
    @Override
    public List<GoodsScheduleDTO> getScheduleGoods() {
        LambdaUpdateWrapper<GoodsScheduleDO> goodsScheduleWrapper = new LambdaUpdateWrapper<>();
        goodsScheduleWrapper.eq(GoodsScheduleDO::getIsSuccess, StatusEnum.STATUS_NO.getCode());
        List<GoodsScheduleDO> goodsSchedules = goodsScheduleMapper.selectList(goodsScheduleWrapper);
        return convertGoodsScheduleDoList2DtoList(goodsSchedules);
    }

    /**
     * 更新调度状态
     *
     * @param goodsScheduleDTO 定时上架调度的商品
     */
    @Override
    public void updateGoodsScheduleStatus(GoodsScheduleDTO goodsScheduleDTO) {
        GoodsScheduleDO goodsSchedule = convertGoodsScheduleDto2Do(goodsScheduleDTO);
        goodsScheduleMapper.updateById(goodsSchedule);
    }

    /**
     * 根据商品SPU id 获取sku id集合
     *
     * @param id 商品SPU id
     * @return List<Long> sku id集合
     */
    @Override
    public List<Long> getSkuIdListBySpuId(Long id) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(id == null);

        List<GoodsSkuDO> goodsSkuList = goodsSkuMapper.selectList(
                Wrappers.<GoodsSkuDO>lambdaQuery()
                        .select(GoodsSkuDO::getId)
                        .eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .eq(GoodsSkuDO::getGoodsId, id));
        List<Long> skuIdList = new ArrayList<>();
        for (GoodsSkuDO goodsSku : goodsSkuList) {
            skuIdList.add(goodsSku.getId());
        }
        return skuIdList;
    }

    /**
     * 根据商品SPU id 集合获取sku id集合
     *
     * @param ids 商品SPU id集合
     * @return List<Long> sku id集合
     */
    @Override
    public List<Long> getSkuIdListBySpuIds(List<Long> ids) {
        List<Long> skuIdList = new ArrayList<>();
        List<GoodsSkuDO> goodsSkuList = goodsSkuMapper.selectList(
                Wrappers.<GoodsSkuDO>lambdaQuery()
                        .select(GoodsSkuDO::getId)
                        .eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .in(GoodsSkuDO::getGoodsId, ids));

        for (GoodsSkuDO goodsSku : goodsSkuList) {
            skuIdList.add(goodsSku.getId());
        }
        return skuIdList;
    }

    private GoodsScheduleDO convertGoodsScheduleDto2Do(GoodsScheduleDTO goodsScheduleDto) {
        GoodsScheduleDO goodsSchedule = null;
        try {
            goodsSchedule = goodsScheduleDto.clone(GoodsScheduleDO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSchedule;
    }

    /**
     * 将定时上架调度的商品DO对象转换为DTO对象
     *
     * @param goodsSchedules 定时上架调度的商品 DO 集合列表
     * @return List<GoodsScheduleDTO> 定时上架调度的商品 DTO
     */
    private List<GoodsScheduleDTO> convertGoodsScheduleDoList2DtoList(List<GoodsScheduleDO> goodsSchedules) {
        List<GoodsScheduleDTO> goodsDtos = null;
        try {
            goodsDtos = ObjectUtils.convertList(goodsSchedules, GoodsScheduleDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsDtos;
    }

    /**
     * 将商品sku供应商 DO对象转换为DTO对象
     *
     * @param supplier 商品sku供应商 DO
     * @return GoodsDTO 商品sku供应商 DTO
     */
    private List<SupplierDTO> convertSupplierDoList2DtoList(List<SupplierDO> supplier) {
        List<SupplierDTO> supplierDtoList = null;
        try {
            supplierDtoList = ObjectUtils.convertList(supplier, SupplierDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return supplierDtoList;
    }

    /**
     * 将商品DO对象转换为DTO对象
     *
     * @param goods 商品sku DO
     * @return GoodsDTO 商品sku DTO
     */
    private GoodsDTO convertGoodsDo2Dto(GoodsDO goods) {
        GoodsDTO goodsDto = null;
        try {
            goodsDto = goods.clone(GoodsDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsDto;
    }

    /**
     * 将商品spu和税收对应关系DO数据持久化对象转换为DTO对象
     *
     * @param goodsTaxDo 商品spu和税收对应关系DO数据持久化对象
     * @return GoodsTaxDTO 商品spu和税收对应关系DTO数据传输对象
     */
    private GoodsTaxDTO convertGoodsTaxDo2Dto(GoodsTaxDO goodsTaxDo) {
        GoodsTaxDTO goodsTaxDto = null;
        try {
            goodsTaxDto = goodsTaxDo.clone(GoodsTaxDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsTaxDto;
    }

    /**
     * 将商品sku DTO对象转换为DO对象
     *
     * @param goodsSkuDto 商品sku DTO
     * @return GoodsSku 商品sku DO
     */
    private GoodsSkuDO convertGoodsSkuDto2Do(GoodsSkuDTO goodsSkuDto) {
        GoodsSkuDO goodsSku = null;
        try {
            goodsSku = goodsSkuDto.clone(GoodsSkuDO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSku;
    }

    /**
     * 将商品DTO对象转换为DO对象
     *
     * @param goodsDto 将商品DTO
     * @return Goods 商品DO
     */
    private GoodsDO convertGoodsDto2Do(GoodsDTO goodsDto) {
        GoodsDO goods = null;
        try {
            goods = goodsDto.clone(GoodsDO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goods;
    }

    /**
     * 将商品DO对象集合转换为DTO对象集合
     *
     * @param goods 商品DO集合
     * @return List<GoodsDTO> 商品DTO对象集合
     */
    private List<GoodsDTO> convertGoodsDoList2DtoList(List<GoodsDO> goods) {
        List<GoodsDTO> goodsDtoList = null;
        try {
            goodsDtoList = ObjectUtils.convertList(goods, GoodsDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsDtoList;
    }

    private static Long getWorkId() {
        try {
            String hostAddress = Inet4Address.getLocalHost().getHostAddress();
            int[] ints = org.apache.commons.lang3.StringUtils.toCodePoints(hostAddress);
            int sums = 0;
            for (int b : ints) {
                sums += b;
            }
            return (long) (sums % 32);
        } catch (Exception e) {
            // 如果获取失败，则使用随机数备用
            return RandomUtils.nextLong(0, 31);
        }
    }

    private static Long getDataCenterId() {
        try {
            int[] ints = org.apache.commons.lang3.StringUtils.toCodePoints(InetAddress.getLocalHost().getHostName());
            int sums = 0;
            for (int i : ints) {
                sums += i;
            }
            return (long) (sums % 32);
        } catch (Exception e) {
            // 如果获取失败，则使用随机数备用
            return RandomUtils.nextLong(0, 31);
        }
    }

    /**
     * 将组合商品和物料的sku对应关系DTO对象集合转换为DO对象
     *
     * @param commoditySupplySkuRelationshipDto 组合商品和物料的sku对应关系DTO
     * @return CommoditySupplySkuRelationship 组合商品和物料的sku对应关系DO
     */
    private CommodityMaterialSkuRelationshipDO convertCommoditySupplySkuRelationshipDto2Do(
            CommodityMaterialSkuRelationshipDTO commoditySupplySkuRelationshipDto) {
        CommodityMaterialSkuRelationshipDO targetCommoditySupplySkuRelationship = null;
        try {
            targetCommoditySupplySkuRelationship =
                    commoditySupplySkuRelationshipDto.clone(CommodityMaterialSkuRelationshipDO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return targetCommoditySupplySkuRelationship;
    }


    /**
     * 将商品图片DO对象集合转换为DTO对象集合
     *
     * @param goodsPictures 商品图片DTO集合
     * @return List<GoodsPictureDTO> 商品图片DTO对象集合
     */
    private List<GoodsPictureDTO> convertGoodsPictureDoList2DtoList(List<GoodsPictureDO> goodsPictures) {
        List<GoodsPictureDTO> goodsPictureDtos = null;
        try {
            goodsPictureDtos = ObjectUtils.convertList(goodsPictures, GoodsPictureDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsPictureDtos;
    }

    /**
     * 将商品sku属性 DO对象集合转换为VO对象集合
     *
     * @param goodsSkuPropertyValues 商品sku 属性DO集合
     * @return List<GoodsSkuPropertyValueDTO> 商品sku属性 DTO对象集合
     */
    private List<GoodsSkuPropertyValueDTO> convertGoodsSkuPropertyValueList2DtoList(
            List<GoodsSkuPropertyValueDO> goodsSkuPropertyValues) {
        List<GoodsSkuPropertyValueDTO> goodsSkuPropertyValueDtos = null;
        try {
            goodsSkuPropertyValueDtos = ObjectUtils.convertList(goodsSkuPropertyValues,
                    GoodsSkuPropertyValueDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSkuPropertyValueDtos;
    }

    private List<CommodityMaterialSkuRelationshipDTO> convertCommodityMaterialSkuRelationshipList2DtoList(
            List<CommodityMaterialSkuRelationshipDO> commodityMaterialSkuRelationships) {
        List<CommodityMaterialSkuRelationshipDTO> commodityMaterialSkuRelationshipDtos = null;
        try {
            commodityMaterialSkuRelationshipDtos = ObjectUtils.convertList(commodityMaterialSkuRelationships,
                    CommodityMaterialSkuRelationshipDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return commodityMaterialSkuRelationshipDtos;
    }

    /**
     * 将商品sku DO对象集合转换为DTO对象集合
     *
     * @param goodsSkus 商品sku DO集合
     * @return List<GoodsSkuDTO> 商品sku DTO对象集合
     */
    private List<GoodsSkuDTO> convertGoodsSkuList2DtoList(List<GoodsSkuDO> goodsSkus) {
        List<GoodsSkuDTO> goodsSkuDtos = null;
        try {
            goodsSkuDtos = ObjectUtils.convertList(goodsSkus, GoodsSkuDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSkuDtos;
    }

    /**
     * 将商品sku DO对象集合转换为DTO对象集合
     *
     * @param goodsSkuDtos 商品sku DTO集合
     * @return List<GoodsSku> 商品sku DO对象集合
     */
    private List<GoodsSkuDO> convertGoodsSkuDtoList2DoList(List<GoodsSkuDTO> goodsSkuDtos) {
        List<GoodsSkuDO> goodsSkus = null;
        try {
            goodsSkus = ObjectUtils.convertList(goodsSkuDtos, GoodsSkuDO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSkus;
    }

    /**
     * 获取物料skudto
     *
     * @param materialSkuRelationships 物料sku信息
     * @param mSpuid                   物料spuid
     * @return
     */
    private List<GoodsMateriaSkuDTO> getGoodsMateriaSkuByDO(List<CommodityMaterialSkuRelationshipDO> materialSkuRelationships, Long mSpuid) {
        return materialSkuRelationships.stream().filter(m -> mSpuid.equals(m.getMaterialSpuId())).map(m -> {
            GoodsMateriaSkuDTO goodsMateriaSkuDTO = new GoodsMateriaSkuDTO();
            goodsMateriaSkuDTO.setMateriaSkuId(m.getMaterialSkuId());
            goodsMateriaSkuDTO.setMateriaSkuCode(m.getMaterialSkuCode());
            goodsMateriaSkuDTO.setComposeNumber(m.getComposeNumber());
            goodsMateriaSkuDTO.setMateriaSkuSpecName(m.getSpecName());
            return goodsMateriaSkuDTO;
        }).collect(Collectors.toList());
    }

    /**
     * 封装组合商品的物料信息
     *
     * @param materialSpuRelationships
     * @param materialSkuRelationships
     * @return
     */
    private GoodsMateriaDTO getGoodsMateriaCompose(List<CommodityMaterialSpuRelationshipDO> materialSpuRelationships, List<CommodityMaterialSkuRelationshipDO> materialSkuRelationships) {
        //组合物料spu信息
        List<GoodsMateriaSpuDTO> goodsMateriaSpus = materialSpuRelationships.stream().map(m -> {
            GoodsMateriaSpuDTO goodsMateriaSpuDTO = new GoodsMateriaSpuDTO();
            goodsMateriaSpuDTO.setMateriaSpuId(m.getMaterialSpuId());
            goodsMateriaSpuDTO.setMateriaSpuName(m.getMaterialSpuName());
            goodsMateriaSpuDTO.setMateriaSpuCode(m.getMaterialSpuCode());
            goodsMateriaSpuDTO.setSkus(getGoodsMateriaSkuByDO(materialSkuRelationships, m.getMaterialSpuId()));
            return goodsMateriaSpuDTO;
        }).collect(Collectors.toList());
        //获取物料skuid信息
        List<Long> skuids = materialSkuRelationships.stream().map(m -> {
            return m.getMaterialSkuId();
        }).collect(Collectors.toList());
        return new GoodsMateriaDTO(goodsMateriaSpus, skuids);
    }

    /**
     * 封装商品sku信息
     *
     * @param list
     * @return
     */
    private GoodsSkuStockIdDTO getGoodsSkuStockWares(List<GoodsSkuDO> list) {
        List<Long> skuids = new ArrayList<>(list.size());
        List<GoodsSkuStockWareDTO> goodsSkuStockWareDTOS = list.stream().map(po -> {
            GoodsSkuStockWareDTO goodsSkuStockWareDTO = new GoodsSkuStockWareDTO();
            goodsSkuStockWareDTO.setSkuId(po.getId());
            goodsSkuStockWareDTO.setSkuCode(po.getSkuCode());
            goodsSkuStockWareDTO.setGoodsName(po.getGoodsName());
            goodsSkuStockWareDTO.setWeight(po.getWeight());
            skuids.add(po.getId());
            return goodsSkuStockWareDTO;
        }).collect(Collectors.toList());
        return new GoodsSkuStockIdDTO(goodsSkuStockWareDTOS, skuids);
    }

    /**
     * 添加库存- 组合商品-物料对应关系封装
     *
     * @param skus
     * @param details
     * @param materials
     */
    private void thirdGoodsMaterialList(List<GoodsSkuStockVO> skus, List<CommodityApplyDetailDTO> details, List<CommodityApplyMaterialDTO> materials) {
        List<CommodityMaterialSkuRelationshipDO> skuRelationshipDOs = commoditySupplySkuRelationshipMapper.selectList(
                Wrappers.<CommodityMaterialSkuRelationshipDO>lambdaQuery()
                        .in(CommodityMaterialSkuRelationshipDO::getSkuId,
                                skus.stream().map(s -> {
                                    Long skuid = s.getSkuId();
                                    return skuid;
                                }).collect(Collectors.toList())));
        //如果商品物料对应关系为空抛出异常
        ExceptionEnum.FAIL_GOODS_MATERIAL_RELATION_NULL.doThrowIf(CollectionUtil.isEmpty(skuRelationshipDOs));
        skus.stream().forEach(sk -> {
            CommodityApplyDetailDTO skuApply = new CommodityApplyDetailDTO();
            skuApply.setSkuId(sk.getSkuId());
            skuApply.setSkuCode(sk.getSkuCode());
            skuApply.setPreStockNum(sk.getPreStorage());
            skuApply.setStockNum(sk.getStockQuantity());
            skuApply.setSpecName(sk.getGoodsName());
            if (skuRelationshipDOs.size() > NumberConstant.NUMBER_ZERO) {
                List<CommodityMaterialSkuRelationshipDO> skuRelationships = skuRelationshipDOs.stream().filter(skr -> sk.getSkuId().equals(skr.getSkuId())).collect(Collectors.toList());
                if (skuRelationships.size() > NumberConstant.NUMBER_ZERO) {
                    //封装sku物料数量dto
                    skuRelationships.stream().forEach(relation -> {
                        CommodityApplyMaterialDTO materialApplyDTO = new CommodityApplyMaterialDTO();
                        materialApplyDTO.setMaterialId(relation.getMaterialSkuId());
                        materialApplyDTO.setSkuId(sk.getSkuId());
                        materialApplyDTO.setSkuCode(sk.getSkuCode());
                        materialApplyDTO.setMaterialNum(relation.getComposeNumber() != null ? relation.getComposeNumber() : 0);
                        materials.add(materialApplyDTO);
                    });
                }
            }
            details.add(skuApply);
        });
    }

    /**
     * 添加库存- 单商品-物料对应关系封装
     *
     * @param skus
     * @param details
     * @param materials
     */
    private void notThirdGoodsMaterialList(List<GoodsSkuStockVO> skus, List<CommodityApplyDetailDTO> details, List<CommodityApplyMaterialDTO> materials) {
        skus.stream().forEach(sk -> {
            CommodityApplyDetailDTO skuApply = new CommodityApplyDetailDTO();
            skuApply.setSkuId(sk.getSkuId());
            skuApply.setSkuCode(sk.getSkuCode());
            skuApply.setPreStockNum(sk.getPreStorage());
            skuApply.setStockNum(sk.getStockQuantity());
            skuApply.setSpecName(sk.getGoodsName());
            CommodityApplyMaterialDTO materialApplyDTO = new CommodityApplyMaterialDTO();
            materialApplyDTO.setMaterialId(sk.getMaterialSkuId());
            materialApplyDTO.setSkuId(sk.getSkuId());
            materialApplyDTO.setSkuCode(sk.getSkuCode());
            materialApplyDTO.setMaterialNum(NumberConstant.NUMBER_ONE.intValue());
            materials.add(materialApplyDTO);
            details.add(skuApply);
        });
    }

    private ClearSkuMaterialDTO packClearDto(GoodsDO po) {
        List<GoodsMaterialRelationDTO> relations = new ArrayList<>();
        List<Long> skuIds = new ArrayList<>();
        //获取sku信息集合
        List<GoodsSkuDO> skus = goodsSkuMapper.selectList(
                Wrappers.<GoodsSkuDO>lambdaQuery()
                        .eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .eq(GoodsSkuDO::getGoodsId, po.getId()));
        ExceptionEnum.FAIL_GOODS_SKU_EXIST.doThrowIf(CollectionUtil.isEmpty(skus));
        skus.stream().forEach(sku -> {
            skuIds.add(sku.getId());
            //非组合商品直接封装
            if (!GoodsType.COMPOSE.equals(po.getGoodsType())) {
                GoodsMaterialRelationDTO goodsMaterialRelationDTO = new GoodsMaterialRelationDTO();
                goodsMaterialRelationDTO.setSkuId(sku.getId());
                goodsMaterialRelationDTO.setMaterialId(sku.getMaterialSkuId());
                goodsMaterialRelationDTO.setCompNum(NumberConstant.NUMBER_ONE.intValue());
                relations.add(goodsMaterialRelationDTO);
            }
        });
        //处理组合商品对应关系
        if (GoodsType.COMPOSE.equals(po.getGoodsType())) {
            List<CommodityMaterialSkuRelationshipDO> skuRelationshipDOs = commoditySupplySkuRelationshipMapper.selectList(
                    Wrappers.<CommodityMaterialSkuRelationshipDO>lambdaQuery()
                            .in(CommodityMaterialSkuRelationshipDO::getSkuId, skuIds));
            //如果商品物料对应关系为空抛出异常
            ExceptionEnum.FAIL_GOODS_MATERIAL_RELATION_NULL.doThrowIf(CollectionUtil.isEmpty(skuRelationshipDOs));
            skuRelationshipDOs.stream().forEach(sku -> {
                GoodsMaterialRelationDTO goodsMaterialRelationDTO = new GoodsMaterialRelationDTO();
                goodsMaterialRelationDTO.setSkuId(sku.getSkuId());
                goodsMaterialRelationDTO.setMaterialId(sku.getMaterialSkuId());
                goodsMaterialRelationDTO.setCompNum(sku.getComposeNumber() != null ? sku.getComposeNumber() : NumberConstant.NUMBER_ZERO.intValue());
                relations.add(goodsMaterialRelationDTO);
            });
        }
        return new ClearSkuMaterialDTO(skuIds, relations);
    }

    public FreightTempDTO freightInfo(Long id) {
        //获取模板信息
        FreightTemplateDO ftDO = freightTemplateMapper.selectOne(
                Wrappers.<FreightTemplateDO>lambdaQuery()
                        .eq(FreightTemplateDO::getId, id)
                        .eq(FreightTemplateDO::getIsDel, StatusEnum.STATUS_NO.getCode()));
        ExceptionEnum.FAIL_FREIGHT_NULL.doThrowIf(ftDO == null);
        //获取模板的详情
        List<FreightTemplateExtendDO> dos = freightTemplateExtendMapper.selectList(
                Wrappers.<FreightTemplateExtendDO>lambdaQuery()
                        .eq(FreightTemplateExtendDO::getTemplateId, id));
        return new FreightTempDTO(ftDO.getId(), ftDO.getTemplateName(), ftDO.getRule(), pos2Dtos(dos));
    }

    private List<FreightTempInfoDTO> pos2Dtos(List<FreightTemplateExtendDO> pos) {
        return pos.stream().map(po -> {
            FreightTempInfoDTO dto = null;
            try {
                dto = po.clone(FreightTempInfoDTO.class);
            } catch (Exception e) {

            }
            return dto;
        }).collect(Collectors.toList());
    }
}
